home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGSCAL / TBUTIL1.LZH / TERM.ASM < prev    next >
Assembly Source File  |  1984-02-22  |  34KB  |  1,052 lines

  1. .xlist
  2. ;-----------------------------------------------------------------------------
  3. ;                             TELECOMM
  4. ;                      FAST TELECOMMUNICATION
  5. ;
  6. ;   This program handles communication between two computers running the
  7. ;   program.  It allows you to either transmit or receive a file with
  8. ;   error checking.  An array is used as the buffer to transmit and receive
  9. ;   to/from.  The program will alert the calling program of any errors.
  10. ;   Buffered communications are handled by a modified version of CJ Dunford's
  11. ;   Dumterm program from PC Tech Journal, Jan '84, p144-186.
  12. ;-----------------------------------------------------------------------------
  13.  
  14.  
  15. bufsize      equ     512                ;1/2K Buffer
  16.  
  17. LF           equ     0Ah
  18. CR           equ     0Dh
  19. ESC          equ     1Bh
  20.  
  21. RECEIVE       EQU    1                  ;Blocks are to be SENT
  22. TRANSMIT      EQU    2                  ;Blocks are to be RECEIVED
  23.  
  24. CHK_SUM_ERR   EQU    1                  ;We have a CheckSum Error
  25. TIME_OUT_ERR  EQU    2                  ;We have a TIMEOUT Error
  26. PROTOCOL_ERR  EQU    3                  ;We have a PROTOCOL COMM Error
  27. NUM_OF_UNITS  EQU    0F000h             ;Each unit is 0.00x seconds
  28.  
  29.         ;Codes sent by TRANSMIT:
  30. TRANS_SIZE    EQU    0F0h               ;Send blk of NN size
  31. DONE_TRANS    EQU    0F1h               ;Transmission is done
  32. CHK_SUM_IS    EQU    0F2h               ;Checksum is NNNN
  33.  
  34.         ;Codes sent by RECEIVE:
  35. OK_SEND       EQU    0F3h               ;Ok to send DATA
  36. OK_DONE       EQU    0F4h               ;We're done too
  37. CHK_SUM_OK    EQU    0F5h               ;Checksum is OK
  38. ERR_RE_XMIT   EQU    0F6h               ;Comm. Error, send again
  39.  
  40.  
  41. ; ------- BIOS calls
  42.  
  43. RS232        equ     14h            ;RS232 service
  44. kbd_io       equ     16h            ;Keyboard service
  45.  
  46. ; ------- INS8250 registers
  47.  
  48. THR          equ     3F8h           ;Trans holding register (write)
  49. RBR          equ     3F8h           ;Recieve buffer register (read)
  50. IER          equ     3F9h           ;Interrupt inable register
  51. LCR          equ     3FBh           ;Line control register
  52.                                     ;  Bit 7 of LCR is "DLAB". DLAB must
  53.                                     ;  be zero to access THR, RBR, IER.
  54. MCR         equ      3FCh           ;Modem control register
  55. LSR         equ      3FDh           ;Line status register
  56. MSR         equ      3FEh           ;Modem status register
  57.  
  58. ; ------- Comm parameter definition
  59. ; Refer to IBM Tech Ref manual page A-20
  60. ; See PROC INIT for usage.
  61. ; ---------------------------------------
  62. commparm   record baud:3, parity:2, stopbits:1, wordbits:2
  63.  
  64. ; Buad rates
  65. B110        equ      000b
  66. B150        equ      001b
  67. B300        equ      010b
  68. B600        equ      011b
  69. B1200       equ      100b
  70. B2400       equ      101b
  71. B4800       equ      110b
  72. B9600       equ      111b
  73.  
  74. ; Parity
  75. no_parity    equ     00b
  76. odd_parity   equ     01b
  77. even_parity  equ     11b
  78.  
  79. ; Stop bits
  80. stop1        equ     0
  81. stop2        equ     1
  82.  
  83. ; Data bits
  84. data7        equ     10b
  85. data8        equ     11b
  86.  
  87.  
  88. ;*****************************
  89. ;         MACROS
  90. ;*****************************
  91.  
  92. MWRITE  MACRO   string
  93.         local   mstrng, mw10
  94.         jmp     mw10
  95. mstrng  db      string,lf,cr,'$'
  96. mw10:   push    dx
  97.         lea     dx, mstrng[bp]
  98.         call    strdisp
  99.         pop     dx
  100.         ENDM
  101.  
  102.  
  103. MPOP    MACRO   DEST                    ;Move the stack addr. into DEST
  104.         POP     AX
  105.         MOV     DEST, AX
  106.         ENDM
  107.  
  108. MPUSH   MACRO   SOURCE                   ;Push the SOURCE onto the Stack
  109.         MOV     AX, SOURCE
  110.         PUSH    AX
  111.         ENDM
  112.  
  113. MVWRD   MACRO   DEST, SOURCE             ;Move %1 <== %2
  114.         MOV     si, SOURCE
  115.         MOV     DEST, si
  116.         ENDM
  117.  
  118. MVWRDsi MACRO   DEST, SOURCE             ;Move %1 <== [%2]  (source indirect)
  119.         MOV     si, SOURCE
  120.         mov     si, ds:[si]
  121.         MOV     DEST, si
  122.         ENDM
  123.  
  124. MVWRDdi MACRO   DEST, SOURCE             ;Move [%1] <== %2  (dest indirect)
  125.         MOV     di, DEST
  126.         mov     si, SOURCE
  127.         MOV     ds:[di], si
  128.         ENDM
  129.  
  130.  
  131. @bioscall MACRO call_num, parm
  132. ;; Generates an 'INT call_num', with parm in AH
  133.             IFNB     <parm>
  134.               mov    ah,parm
  135.             ENDIF
  136.             int      call_num
  137.             ENDM
  138.  
  139.  
  140. @doscall MACRO function, parm
  141. ;; Generates a DOS function call with parm in AH
  142.             IFNB     <parm>
  143.               mov    al,parm
  144.             ENDIF
  145.             @bioscall 21h,function
  146.             ENDM
  147.  
  148.  
  149. ;******************************
  150. ;    DATA & STACK STORAGE
  151. ;******************************
  152.  
  153.  
  154. code segment para public 'code'
  155.              assume cs:code, ds:code, ss:code, es:code
  156.              public    telecomm
  157.  
  158. telecomm      proc     near
  159.  
  160.               CALL   BEGIN
  161.  
  162. BasePage      DW     ?                  ;Storage for BP reg
  163. DataSeg       DW     ?                  ;Storage for DS reg
  164.  
  165. ERROR         DW     ?                  ;Parameters passed by the stack
  166. BLK_SIZE      DW     ?
  167. BUF_SIZE      DW     ?
  168. COMMAND       DW     ?
  169.  
  170. ARRAY         DW     ?
  171. BUF_ARRAY     DB     10000 DUP (?)       ;4K Buffer
  172.  
  173. RETURN        DW     ?                  ;Temporary registers
  174. BLK_SZ        DW     ?
  175. BUF_SZ        DW     ?
  176. ERR           DW     ?
  177.  
  178. CHK_SUM_1     DW     ?                  ;Data checksum regs
  179. CHK_SUM_2     DW     ?
  180.  
  181. TIME_CNT      DW     ?                  ;Used to count time in inp loop
  182. TIME_CNT1     DW     ?
  183. TEMP          DW     ?
  184. ERR_COUNT     DW     ?
  185. TMP_ARRAY     DW     ?
  186.  
  187.  
  188.  
  189. ; ----- The string section
  190. sgreeting      db      '--- ONLINE ---',cr,lf,'$'
  191. sgoodbye       db      cr,lf,'--- OFFLINE ---',cr,lf,'$'
  192. serr1          db      '<R>$'          ;RS232 receive error
  193. serr2          db      '<S>$'          ;RS232 send error
  194. serr3          db      '<B>$'          ;Receive buffer overflow error
  195.  
  196. ; ----- Flags
  197. brcv_err       db     0                ;Nonzero on RS232 receive error
  198. boverflow      db     0                ;Nonzero on buffer overflow
  199. bdoneflag      db     0                ;Nonzero after ESC from kbd
  200.  
  201. ; ----- Receive data buffer and associated pointers
  202. ; >> Buffer is empty if head point4er = tail pointer
  203. wbufhead       dw     ?                ;Pointer to head of buffer
  204. wbuftail       dw     ?                ;Pointer to tail of buffer
  205. buffer         db     BUFSIZE dup (?)
  206. bufend         dw     ?
  207.  
  208.  
  209.  
  210.  
  211. ;* * * * * * * * * * * * * * * * *
  212. ;         PROGRAM BODY
  213. ;* * * * * * * * * * * * * * * * *
  214.  
  215. BEGIN   PROC     NEAR
  216.         pop      ax                    ;Return the data seg
  217.         sub      ax, 3                 ;Adjust it
  218.         mov      di, ax                ;Ofset pointer to index reg
  219.         mov      BasePage[di], bp      ;Save old BP for exit
  220.         mov      DataSeg[di], ds       ;Save old DS for exit
  221.         mov      bp, di                ;Make BP the pointer
  222.  
  223.         MPOP     RETURN[bp]            ;Save the RETURN Addr.
  224.         MPOP     ERROR[bp]             ;Error code on exit
  225.         pop      ax
  226.         MPOP     BLK_SIZE[bp]          ;Length to send before chcksum
  227.         pop      ax
  228.         MPOP     BUF_SIZE[bp]          ;Size of data in BLK units
  229.         pop      ax
  230.         MPOP     COMMAND[bp]           ;What to do
  231.         pop      ax
  232.         MPUSH    RETURN[bp]            ;Replace the Return Addr.
  233.         CALL    OPEN_RS                ;Set us up
  234.         CALL    INITIALIZE             ;Clear vars
  235.  
  236.         CALL    MAIN                   ;Do telecommunication
  237.  
  238.         CALL    CLOSE_RS
  239.         mov     bp, BasePage[bp]       ;Restore the BasePage
  240.         RET
  241. BEGIN   ENDP
  242.  
  243.  
  244.  
  245. ;------WRITE_HEX------------------------------
  246. ; Displays 4 hexadecimal numbers contained in AX
  247. ; Entry:
  248. ;   AX ==> 4 Hex numbers
  249. ; Exit:
  250. ;   All regs but AX restored
  251. ;----------------------------------------------
  252.  
  253.  
  254. Write_HEX    PROC
  255.              push   bx                      ;Save regs
  256.              push   cx
  257.              push   dx
  258.              mov    bx, ax
  259.              mov    cx, 12
  260.              shr    ax, cl
  261.              call   pr_one_hex
  262.              mov    ax, bx
  263.              mov    cx, 8
  264.              shr    ax, cl
  265.              call   pr_one_hex
  266.              mov    ax, bx
  267.              mov    cx, 4
  268.              shr    ax, cl
  269.              call   pr_one_hex
  270.              mov    ax, bx
  271.              call   pr_one_hex
  272.              pop    dx
  273.              pop    cx
  274.              pop    bx
  275.              ret
  276.  
  277. pr_one_hex:  and    ax, 000Fh               ;Mask LSD
  278.              cmp    ax,9
  279.              ja     wa20
  280.              add    ax, '0'
  281.              jmp    wa30
  282. wa20:        add    ax, 'A'-10
  283. wa30:        mov    dx, ax
  284.              @doscall 2                     ;Print the char
  285.              ret
  286.  
  287. Write_HEX    ENDP
  288.  
  289.  
  290.  
  291.              ;START OF PROGRAM:
  292.  
  293.  
  294. INITIALIZE   PROC   NEAR                        ;Zero out variables
  295.         MOV   ERR[bp], 0000
  296.         MOV   TIME_CNT[bp],  0000
  297.         MOV   CHK_SUM_1[bp], 0000
  298.         MOV   CHK_SUM_2[bp], 0000
  299.  
  300.         MVWRDsi BUF_SZ[bp], BUF_SIZE[bp]              ;Move params to vars
  301.         MVWRDsi BLK_SZ[bp], BLK_SIZE[bp]
  302.  
  303.         lea     ax, buf_array[bp]
  304.         mov     array[bp], ax
  305.         ret
  306. INITIALIZE  ENDP
  307.  
  308.  
  309.  
  310. MAIN    PROC  NEAR
  311.         mov     si, command[bp]
  312.         cmp  byte ptr ds:[si], transmit         ;Shall we Transmit
  313.         JE  SHORT  M010                         ;Go on to TRANSMT
  314.         CALL    RECV_IT                         ;Read in the data
  315.         JMP SHORT  M090
  316. M010:   CALL    TRANS_IT                        ;Transmit the data
  317.  
  318. M090:   MOV     AX, ERR[bp]
  319.         MOV     AH, 00                          ;Zero MSD
  320.         mov     bx, error[bp]
  321.         MOV     ds:[bx], AX
  322.         RET
  323. MAIN    ENDP
  324.  
  325.  
  326. RECV_IT PROC  NEAR
  327.  
  328. ; ---- Receive the data
  329.         MOV     ERR_COUNT[bp], 00               ;Zero Error Count
  330.  
  331. R010:   CALL    READ_RS                         ;Get the trans code
  332.         MOV     byte ptr TEMP[bp], al           ;Save for later
  333.         cmp     err[bp], 0
  334.         je      R015
  335.         JMP     R999                            ;Error, Now exit
  336.  
  337. R015:   MOV     al, byte ptr  TEMP[bp]          ;Get back INP
  338.         CMP     AL, TRANS_SIZE                  ;Code for blk_size
  339.         JE  SHORT  R030
  340.         CMP     AL, DONE_TRANS                  ;Code for EOT
  341.         JNE SHORT  R020
  342.         MOV     AL, OK_DONE                     ;Tell them we're done
  343.         CALL    WRITE_RS
  344.         MVWRDdi BUF_SIZE[bp], BUF_SZ[bp]        ;Make BUF_SZ avail to caller
  345.         JMP     R999
  346.  
  347. R020:   CALL    PRTCL_ERR_RPT                   ;Report Protocol error
  348.         JMP     R999
  349.  
  350. R030:   CALL    READ_RS                         ;Read in BLK_SIZE
  351.         MOV  byte ptr BLK_SZ[bp], AL
  352.         cmp     ERR[bp], 00                     ;If there was an err, exit
  353.         JNZ     R999                            ;Error, Now exit
  354.  
  355. R040:   MOV     AL, OK_SEND                     ;Tell them its OK to trans
  356.         CALL    WRITE_RS
  357.  
  358.         MVWRD   TMP_ARRAY[bp], ARRAY[bp]        ;Save for later
  359.         CALL    ACPT_INFO                       ;Receive the DATA block
  360.         JNE SHORT  R080                         ;Note error, try again
  361.         CALL    VRIFY_CHECKSUM                  ;Check if OK
  362.         JNE SHORT  R080                         ;Go report error
  363.  
  364.         INC     BUF_SZ[bp]                      ;Keep count of BLKs
  365.         MOV     AL, CHK_SUM_OK                  ;Tell them CHK_SUM Ok
  366.         CALL    WRITE_RS
  367.         JMP     R010                            ;Loop for next BLK
  368.  
  369. R080:   MVWRD   ARRAY[bp], TMP_ARRAY[bp]        ;Restore ARRAY pointer
  370.         INC BYTE ptr  ERR_COUNT[bp]
  371.         CMP     ERR_COUNT[bp], 3                ;Can't be more than 3 Errors
  372.         JA      R090                            ;Report Error
  373.  
  374.         MOV     AL, ERR_RE_XMIT                 ;Tell them to send it again
  375.         CALL    WRITE_RS
  376.         JMP     R010
  377.  
  378. R090:   cmp     ERR[bp], 00                     ;Report checksum error
  379.         JNZ     R999                            ;Dont alter a set error flag
  380.         MOV     ERR[bp], CHK_SUM_ERR            ;Set checksum error
  381.  
  382. R999:   RET
  383. RECV_IT ENDP
  384.  
  385.  
  386.  
  387. ACPT_INFO PROC NEAR
  388.  
  389. ; ---- Read in the DATA blk
  390.         MOV     AX, BLK_SZ[bp]                  ;Init BLK_SIZE
  391.         MOV     AH, 00                          ;Zero MSD
  392.         mov     bx, blk_size[bp]
  393.         MOV     ds:[bx], AX
  394.  
  395.         MOV     CHK_SUM_1[bp], 00               ;Zero out Checksum_1
  396.  
  397. A010:   CALL    READ_RS                         ;Read in first char
  398.         MOV     byte ptr TEMP[bp], AL           ;Save for later
  399.         cmp     ERR[bp], 00
  400.         JNZ SHORT  A999                         ;Exit if Err
  401.  
  402.         mov     si, array[bp]                   ;Point to array addr.
  403.         mov     al, byte ptr temp[bp]           ;Move Input to BLK
  404.         mov     byte ptr cs:[si], al
  405.         CALL    CHK_SM_ADD                      ;Add to check sum figure
  406.         INC     ARRAY[bp]
  407.         DEC     BLK_SZ[bp]
  408.         JNZ SHORT A010                          ;Loop till done
  409.  
  410. A999:   RET                                     ;NE means ERROR
  411. ACPT_INFO ENDP
  412.  
  413.  
  414.  
  415. TRANS_IT PROC NEAR
  416.  
  417. ; ---- Transmit the data
  418.         cmp     BLK_SZ[bp], 00                  ;First check Params
  419.         JNZ SHORT T001
  420.         JMP     T999                            ;Exit if 0 BLK_SIZE
  421. T001:   cmp     BUF_SZ[bp], 00
  422.         JNZ SHORT T005
  423.         JMP     T999                            ;Exit if 0 BUF_SIZE
  424.  
  425. T005:   MOV     ERR_COUNT[bp], 00               ;Zero ERR_COUNT
  426.  
  427. T010:   MOV     AL, TRANS_SIZE                  ;Tell them the BLK_SIZE
  428.         CALL    WRITE_RS
  429.         MOV     ax, BLK_SZ[bp]                  ;LSD only
  430.         CALL    WRITE_RS
  431.  
  432.         CALL    READ_RS                         ;Wait for OK_SEND
  433.         cmp     err[bp], 00                     ;If error, then protocol err
  434.         je      T020                            ;Skip if no error
  435.         jmp     T999                            ;Exit, if error
  436. T020:   CMP     al, OK_SEND                     ;Check if INP is OK_SEND
  437.         JE  SHORT T030                          ;No Error, go on
  438.         MOV     ERR[bp], PROTOCOL_ERR           ;Report Protocol Err
  439.         JMP SHORT T999                          ;Exit
  440.  
  441. T030:   MVWRD   TMP_ARRAY[bp], ARRAY[bp]        ;Save if needed later
  442.         CALL    SEND_INFO                       ;Transmit the DATA
  443.         CALL    SEND_CHK_SUM                    ;Check if OK
  444.         JNE SHORT T080                          ;Note Error, Try again
  445.         DEC     BUF_SZ[bp]
  446.         JNZ SHORT T005                          ;Loop up & reset ERR_COUNT
  447.  
  448.         MOV     AL, DONE_TRANS                  ;Tell them we're DONE
  449.         CALL    WRITE_RS
  450.         CALL    READ_RS                         ;Wait for OK_DONE
  451.         cmp     err[bp], 00                     ;If Err, set protocol Err
  452.         JNE SHORT  T999
  453.         CMP     al, OK_DONE                     ;Check INP vs OK_DONE
  454.         JE  SHORT  T999
  455.         MOV     ERR[bp], PROTOCOL_ERR           ;Tell them Protocol Error
  456.         JMP SHORT  T999
  457.  
  458. T080:   cmp     ERR[bp], 00                     ;Repeat if not fatal Error
  459.         JNZ SHORT T090                          ;Mark CHK_SUM_ERR if so
  460.  
  461.         MVWRD   ARRAY[bp], TMP_ARRAY[bp]        ;Restore ARRAY pointer
  462.         INC BYTE ptr ERR_COUNT[bp]
  463.         CMP     ERR_COUNT[bp], 3                ;ERR_COUNT can't be > 3
  464.         JA  short T090                          ;Report Error
  465.         JMP     T010                            ;Try again
  466.  
  467. T090:   cmp     ERR[bp], 00                     ;Report checksum error
  468.         JNZ short  T999                         ;Dont alter a set error flag
  469.         MOV     ERR[bp], CHK_SUM_ERR            ;Set checksum error
  470.  
  471. T999:   RET
  472. TRANS_IT ENDP
  473.  
  474.  
  475.  
  476. SEND_INFO PROC NEAR
  477.  
  478. ; ---- Transmit the DATA
  479.         MOV       CHK_SUM_1[bp], 00             ;Zero CHK_SUM_1
  480.         MVWRDsi   BLK_SZ[bp], BLK_SIZE[bp]      ;Reset the Block size var.
  481.  
  482. Si010:  MOV     si, ARRAY[bp]                   ;Send the Block
  483.         mov     al, cs:[si]
  484.         CALL    CHK_SM_ADD                      ;Add to check sum figure
  485.         CALL    WRITE_RS
  486.         INC WORD ptr ARRAY[bp]
  487.         DEC WORD ptr BLK_SZ[bp]
  488.         JNZ SHORT Si010
  489.  
  490.         MVWRDsi   BLK_SZ[bp], BLK_SIZE[bp]      ;Reset the Block size var.
  491.         RET
  492. SEND_INFO ENDP
  493.  
  494.  
  495.  
  496. CHK_SM_ADD PROC NEAR
  497.  
  498. ; ---- Add Char to check sum figure
  499.         PUSH    AX
  500.         xor     ah, ah                       ;Clear MSD
  501.         ADD     CHK_SUM_1[bp], AX
  502.         POP     AX
  503.         RET
  504. CHK_SM_ADD ENDP
  505.  
  506.  
  507.  
  508. VRIFY_CHECKSUM PROC NEAR
  509.  
  510. ; ---- Verify the equality of the chksums
  511.         CALL    READ_RS                         ;Wait for CHK_SUM code
  512.         CMP     al, CHK_SUM_IS
  513.         JE  SHORT V010                          ;Go on for chk_sum
  514.         CALL    PRTCL_ERR_RPT                   ;Report Protocol error
  515.         JMP SHORT V999
  516.  
  517. V010:   CALL    READ_RS                         ;Get checksum
  518.         MOV  byte ptr CHK_SUM_2[bp], AL
  519.         cmp     err[bp], 00                     ;Set protocol error if error
  520.         JNE SHORT V999                          ;Exit on error
  521.         CALL    READ_RS
  522.         MOV  byte ptr CHK_SUM_2+1[bp], AL
  523.         cmp     err[bp], 00                     ;Set protocol error if error
  524.         JNE SHORT V999                          ;Exit on error
  525.  
  526.         MOV     AX, CHK_SUM_2[bp]               ;Now check equality of chk_sums
  527.         CMP     AX, CHK_SUM_1[bp]
  528. V999:   RET                                     ;NE if error
  529. VRIFY_CHECKSUM ENDP
  530.  
  531.  
  532.  
  533. SEND_CHK_SUM PROC NEAR
  534.  
  535.         MOV     AL, CHK_SUM_IS                  ;Tell them CHK_SUM coming
  536.         CALL    WRITE_RS
  537.         MOV   al, byte ptr  CHK_SUM_1[bp]       ;LSD
  538.         CALL    WRITE_RS
  539.         MOV   al, byte ptr  CHK_SUM_1+1[bp]     ;MSD
  540.         CALL    WRITE_RS
  541.  
  542.         CALL    READ_RS                         ;Wait for CHK_SUM_OK
  543.         cmp     err[bp], 00                     ;If Err then Protocol Err
  544.         JNE SHORT  S999                         ;Exit if Err
  545.         CMP     al, CHK_SUM_OK                  ;Is it CHK_SUM_OK
  546.         JE  SHORT S999                          ;OK, Return
  547.  
  548.         CMP     al, ERR_RE_XMIT                 ;Is it ERR_RE_XMIT
  549.         JNE SHORT S010
  550.         MOV     AL, ERR_RE_XMIT                 ;Set to NE to flag chksum error
  551.         cmp     al, 00                          ;Force setting of NE flag
  552.         JMP SHORT S999                          ;Exit to do again
  553.  
  554. S010:   MOV     ERR[bp], PROTOCOL_ERR           ;Tell them Protocol Error
  555.         cmp     ERR[bp], 00                     ;Force setting of NE flag
  556.  
  557. S999:   RET
  558. SEND_CHK_SUM ENDP
  559.  
  560.  
  561.  
  562. PRTCL_ERR_RPT PROC NEAR
  563.  
  564. ; ---- Report protocol error
  565.         MOV     ERR[bp], PROTOCOL_ERR           ;Flag the comm error
  566.         cmp     ERR[bp], 00                     ;Set NE flag
  567.         RET
  568. PRTCL_ERR_RPT ENDP
  569.  
  570.  
  571.  
  572. WRITE_RS PROC NEAR
  573.         call     RS232_out
  574.         RET
  575. WRITE_RS ENDP
  576.  
  577.  
  578. READ_RS PROC NEAR
  579.         mov   word ptr time_cnt1[bp], 3
  580. Rd001:  mov   word ptr time_cnt[bp], num_of_units
  581.  
  582. Rd010:  dec   TIME_CNT[bp]
  583.         JNZ   SHORT Rd020
  584.         dec   time_cnt1[bp]
  585.         jnz   Rd001
  586.  
  587.         mov     err[bp], TIME_OUT_ERR       ;Signal Timeout
  588.         JMP SHORT Rd999
  589.  
  590. Rd020:  mov     bx, wbufhead[bp]            ;Have char if not equal
  591.         cmp     bx, wbuftail[bp]
  592.         JE  SHORT Rd010                     ;Loop if empty
  593.  
  594.         call    buffer_check                ;Read from .RS232
  595. Rd999:  RET
  596. READ_RS ENDP
  597.  
  598.  
  599. OPEN_RS PROC NEAR
  600.         call     init_rs232
  601.         RET
  602. OPEN_RS ENDP
  603.  
  604. CLOSE_RS PROC NEAR
  605.         call     cleanup_RS232
  606.         RET
  607. CLOSE_RS ENDP
  608.  
  609.  
  610.  
  611.  
  612.  
  613.  
  614. ;* * * * * * * * * * * * * * * * * * * *
  615. ;      PRIMARY RS232 BLOCKS
  616. ;* * * * * * * * * * * * * * * * * * * *
  617.  
  618. ; ------ Init_rs232 --------------------------
  619. ;Program initialization
  620. ;  set up RS232
  621. ;  set up vector for RS232 interrupt (INT 0Ch)
  622. ;  Enable IRQ4
  623. ;  Enable RS232 interrupt on data ready
  624. ; --------------------------------------------
  625.  
  626. init_rs232   proc     near
  627.              lea      ax, buffer[bp]
  628.              mov      wbufhead[bp], ax
  629.              mov      wbuftail[bp], ax
  630.  
  631. ; ----- Initialize RS232 9600,8,N,1
  632.              mov      dx,0
  633.              mov      al,commparm <B1200,no_Parity,stop1,data8>
  634.              @bioscall RS232,0
  635.  
  636. ; ----- Set up INT '0C' for IRQ4
  637.             cli                               ;Interrupts off during setup
  638.             push      ds                      ;Save DS
  639.             lea       dx, ISR[bp]             ;Point to RS232 ISR in DS:DX
  640.             push      cs
  641.             pop       ds
  642.             @doscall 25h,0Ch                  ;Set vector intr for IRQ4
  643.             pop       ds                      ;Restore DS
  644.  
  645. ; ------ Enable IRQ4 on 8259 interrupt controller
  646.             in        al,21h                  ;Get current mask
  647.             and       al,11101111b            ;Reset IRQ4 mask
  648.             out       21h,al                  ;restore to IMR
  649.  
  650. ; ------ Enable 8250 data ready interrupt
  651.             mov      dx,LCR                   ;DX <== LCR
  652.             in       al,dx                    ;reset DLAB for IER access
  653.             and      al,01111111b
  654.             out      dx,al
  655.             mov      dx,IER                   ;address IER
  656.             mov      al,00000001b             ;Enable data-ready interrupt
  657.             out      dx,al
  658.  
  659. ; ------ Enable OUT2 on 8250
  660.             mov      dx,MCR                   ;Address MCR
  661.             mov      al,00001000b             ;Enable OUT2
  662.             out      dx,al
  663.             sti
  664.  
  665. ; ------ Display greeting & return
  666.             lea      dx, sgreeting[bp]        ;Point to greeting
  667.             call     strdisp                  ;Display it
  668.             ret
  669. init_rs232 endp
  670.  
  671. ; ------ Buffer Check ------------------
  672. ; RS232 buffer check
  673. ;
  674. ; This block checks the received data buffer.
  675. ; It functions as follows:
  676. ;
  677. ; If the RS232 input buffer is not empty
  678. ;   Get the first character
  679. ;   Display the character
  680. ;   Update buffer pointer
  681. ; If the RS232 receive error flag is nonzero
  682. ;   Display an error indicator
  683. ;
  684. ; Entry:
  685. ;   No requirement
  686. ; Exit
  687. ;   AX, BX, CX, DX destroyed
  688. ; --------------------------------------
  689.  
  690.  
  691. buffer_check proc near
  692.  
  693. ; ------ Check buffer status
  694.           mov      bx,wbufhead[bp]           ;buffer head pointer
  695.           cmp      bx,wbuftail[bp]           ;buffer empty if head = tail
  696.           je       BC100
  697.  
  698. ; ------ Something in buffer--get 1st char, fix pointers
  699.           mov      al, cs:[bx]               ;get the char
  700.           mov      cl, al                    ;Save for later
  701.           call     incptr                    ;Bump buffer head pointer
  702.           mov      wbufhead[bp],bx
  703.           xor      ah, ah
  704.           ;call     chdisp
  705.  
  706. ; ------ Test RS232 receive status; display errors
  707. BC100:    Test   brcv_err[bp],0FFh           ;Flag nonzero if errors
  708.           jz     BC200                       ;Jump if no errors
  709.           lea    dx, serr1[bp]               ;Point to error msg
  710.           call   strdisp
  711.           mov    brcv_err[bp],0              ;Clear error flag
  712.  
  713. ; ----- Test for buffer overflow; display errors
  714. BC200:
  715.          test    boverflow[bp], 0FFh
  716.          jz      BC300
  717.          mov     boverflow[bp],0             ;Clear the flag
  718.          lea     dx, serr3[bp]               ;Point to error msg
  719.          call    strdisp
  720.  
  721. BC300:   mov     al, cl                      ;Replace input char
  722.          xor     ah, ah                      ;Clear MSD
  723.          ret
  724. buffer_check endp
  725.  
  726. ; ----- KB_CHECK -----------------------------------
  727. ; Check the keyboard.  Functions as follows
  728. ;
  729. ; Check the keyboard status
  730. ; If a characteris available
  731. ;   If the character is ESC
  732. ;     set the done flag
  733. ;   ELSE
  734. ;     send it to RS232 and watch for errors
  735. ;
  736. ;  This routine does not echo the characters to the display.
  737. ;
  738. ; Entry:
  739. ;   No requirement
  740. ; Exit
  741. ;   AX, DX destroyed
  742. ; --------------------------------------
  743.  
  744. kb_check proc near
  745.  
  746. ; ----- Poll keyboard, check chars received
  747.          call    kb_poll                 ;Poll the keyboard
  748.          jz      KBC900                  ;Kbd clear, exit
  749.          cmp     al,ESC                  ;Escape?
  750.          jne     KBC100
  751.          mov     bdoneflag[bp],0FFh      ;Yes, set terminate flag
  752.          jmp     short KBC900
  753.  
  754. ; ----- Send the received char, watch for errors
  755. KBC100:  Call    RS232_out               ;Send it
  756.          test    ah,80h                  ;Time out?
  757.          jz      KBC900
  758.          lea     dx, serr2[bp]           ;Point to error msg
  759.          call    strdisp                 ; and display
  760.  
  761. KBC900:  ret
  762. kb_check endp
  763.  
  764. ; ----- ISR ------------------------------------------------------
  765. ; This is the RS232 interrupt service routine.  It is entered
  766. ; whenever the RS232 port interrupts on a 'data ready'
  767. ; condition.  The routine simply reads the data from the asynch
  768. ; chip and stuffs it in the buffer.  Note that the process of reading
  769. ; the received data register in the 8250 clears IRQ4.  However, the
  770. ; 8259 must be told specifically that the interrupt service is complete.
  771. ;
  772. ; This replaces the function 2 of BIOS interrupt 14h (receive a character
  773. ; over the comm line).  Since it cannot return errors in a register, it
  774. ; puts the error marker in memory at 'brcv_err'.  The error flag is
  775. ; sticky -- a successful read will not clear a prior error indication.
  776. ; This allows the program mainline to examine the error status at its
  777. ; leisure.  Error bits are the same as in RS232OUT, above, except that
  778. ; ONLY the error bits are set, and bit 7 is not used (always 0).  In
  779. ; other words, brcv_err is nonzero only on an error.  Timeout errors
  780. ; are not possible here.
  781. ;
  782. ; The ISR will set the overflow flag if the buffer should overflow.
  783. ; This shouldn't happen.
  784. ; --------------------------------------------------------------------
  785.  
  786. ISR      proc   near
  787.          sti                      ;Allow other interrupts
  788.          push   ax                ;Save all regs used
  789.          push   bx
  790.          push   dx
  791.          push   si
  792.          push   ds
  793.  
  794.          push   cs
  795.          pop    ds
  796.  
  797. ; ---- Get error bits
  798.          mov    dx,LSR                  ;Save address of RS232
  799.          in     al,dx                   ;Get status
  800.          and    al,00011110b            ;Mask non-error bits
  801.          jz     ISR010                  ;Skip error set if OK
  802.          mov    brcv_err[bp],al         ;Set error indicator
  803.  
  804. ; ---- Get incoming character and buffer it
  805. ISR010:  mov    dx,RBR                  ;Receive buffer
  806.          in     al,dx                   ;Get input buffer
  807.          mov    bx,wbuftail[bp]         ;Buffer input pointer
  808.          mov    si,bx                   ;Set pointer before increment
  809.          call   incptr                  ;Bump input pointer
  810.          cmp    bx,wbufhead[bp]         ;Overflow if head = tail
  811.          je     ISR020                  ;Overflow
  812.          mov    cs:[si],al              ;No overflow, save char in buf
  813.          mov    wbuftail[bp],bx         ;And new input pointer
  814.          jmp short ISR999
  815.  
  816. ISR020:  mov    boverflow[bp], 0FFh     ;Set overflow flag
  817.  
  818. ; ---- Signal end of interrupt to 8259
  819. ISR999:  cli
  820.          mov    al,20h                 ;Non-specific EOI
  821.          out    20h,al                 ;Send it
  822.  
  823. ; ---- Restore regs & return.  IRET reenables interrupts
  824.          pop    ds
  825.          pop    si
  826.          pop    dx
  827.          pop    bx
  828.          pop    ax
  829.          iret
  830. ISR endp
  831.  
  832. ; ---- CLEANUP_RS232 --------------
  833. ; End of program housekeeping
  834. ;   -- Disable IRQ4
  835. ;   -- Disable 8250 interrupts
  836. ;   -- Disable OUT2
  837. ;   -- Display offline message
  838. ; ---------------------------------
  839.  
  840. cleanup_rs232 proc near
  841.  
  842.          mov     ax, 0ffffh
  843. cl01:    dec     ax
  844.          jne     cl01
  845. ; ---- Disable IRQ4 on 8259
  846.          cli
  847.          in      al,21h                ;IMR
  848.          or      al,00010000b          ;Mask bit 4 -- IRQ4
  849.          out     21h,al
  850.  
  851. ; ---- Disable 8250 data ready interrupt
  852.          mov     dx, LCR               ;DX <=== LCR
  853.          in      al,dx                 ;Reset DLAB for IER access
  854.          and     al,01111111b
  855.          out     dx,al
  856.          mov     dx,IER                ;Address IER
  857.          mov     al,0                  ;Disable all 8250 interrupts
  858.          out     dx,al
  859.  
  860. ; ---- Disable OUT2 on 8250
  861.        mov      dx,MCR                ;Address MCR
  862.        mov      al,0                  ;Disable OUT2
  863.        out      dx,al
  864.        sti
  865.  
  866. ; ---- Display bye-bye
  867.        lea     dx,  sgoodbye[bp]
  868.        call    strdisp
  869. cleanup_rs232 endp
  870.  
  871.  
  872. ; * * * * * * * * * * * * * *
  873. ;   I/O & General Subroutines
  874. ; * * * * * * * * * * * * * *
  875.  
  876. ; ---- KB_POLL ------------------------------
  877. ; Set/reset Z flag on keyboard buffer status.
  878. ;
  879. ; Entry:
  880. ;   No requirements
  881. ; Exit:
  882. ;   Z = 1 if nothing available
  883. ;   Z = 0 if char available from kbd
  884. ;   IF Z = 0
  885. ;     AL = char
  886. ;     AH = scan code
  887. ;   Other regs preserved
  888. ; ---------------------------------------------
  889.  
  890. kb_poll proc near
  891.         @bioscall  kbd_io,1             ;Poll KB. Sets Z flag if KB bfr empty
  892.         jz         KB999                ;Nothing there
  893.         pushf                           ;Save flag status
  894.         @bioscall  kbd_io,0             ;Something there; get it
  895.         popf
  896. KB999:
  897.         ret
  898. kb_poll endp
  899.  
  900. ; -- RS232_OUT ----------------------------------------
  901. ; RS232 output routine
  902. ;
  903. ; This routine sends one character to the RS232 port.
  904. ; It replaces function 1 of BIOS int 14K.  This is
  905. ; necessary because BIOS will disable the RS232
  906. ; interrupt (by disabling OUT2) every time it is
  907. ; called.
  908. ;
  909. ; Entry:
  910. ;   AL = character to be transmitted
  911. ; Exit:
  912. ;   AH = send status
  913. ;     Bit 7 = 1 if RS232 timeout occurred
  914. ;     If bit 7 = 0
  915. ;       bit 6: trans shift register empty
  916. ;       bit 5: trans holding register empty
  917. ;       bit 4: break detect
  918. ;       bit 3: framing error
  919. ;       bit 2: parity error
  920. ;       bit 1: overrun error
  921. ;       bit 0: data ready
  922. ;  Other regs preserved.
  923. ; -------------------------------------------------------
  924.  
  925. RS232_out proc near
  926.           push   bx             ;Save regs used
  927.           push   cs
  928.           push   dx
  929.           mov    ah, 1
  930.           call   chdisp
  931.  
  932. ; ----- Set up RS232
  933.           mov    bl,al          ;Save char to bl temporarily
  934.           mov    dx,MCR         ;Modem Control Register
  935.           mov    al,00001011b   ; OUT2, DTR, RTS
  936.           out    dx,al
  937.           sub    cx,cx          ;Initialize timeout count
  938.           mov    dx,MSR         ;Modem Status Register
  939.  
  940. ; ----- Wait for DSR
  941. RS100:
  942.           in     al,dx
  943.           test   al,20h         ;Data set ready?
  944.           jnz    RS150          ;Yes
  945.           loop   RS100          ;No, retry till timeout
  946.           mov    ah,80h         ;Set timeout
  947.           jmp    short RSXIT    ;and quit
  948.  
  949. ; ----- Wait for CTS
  950. RS150:
  951.           sub    cx,cx          ;Another timeout count
  952. RS200:
  953.           in     al,dx
  954.           test   al,10h         ;Clear to send?
  955.           jnz    RS250          ;Yes
  956.           loop   RS200          ;No, loop till timeout
  957.           mov    ah,80h         ;TImeout,set flag
  958.           jmp short RSXIT       ;And quit
  959.  
  960. ; ----- Wait for THRE
  961. RS250:
  962.           mov    dx,LSR         ;Line Status Register
  963.           sub    cx,cx          ;Yes another timeout count
  964. RS300:
  965.           in     al,dx          ;LSR status
  966.           test   al,20h         ;Transmit holding reg empty?
  967.           jnz    RS350          ;Yes
  968.           loop   RS300          ;No, loop till timeout
  969.           mov    ah,80h         ;Timeout, set flag
  970.           jmp short RSXIT
  971.  
  972. ; ------ Get line status, send char
  973. RS350:
  974.           mov    ah,al          ;Get line status for return
  975.           and    ah,01111111b   ;Mask out bit 7
  976.           mov    al,bl          ;Restore char to AL
  977.           mov    dx,THR         ;Transmit holding register
  978.           out    dx,al          ;Output it to RS232
  979. RSXIT:
  980.           pop    dx
  981.           pop    cx
  982.           pop    bx
  983.           ret
  984. RS232_out endp
  985.  
  986.  
  987. ; ---- CHDISP ----------------------------------
  988. ; Display the character in AL on the CRT
  989. ; Entry:
  990. ;   AL = char
  991. ; Exit:
  992. ;   All regs restored
  993. ; ----------------------------------------------
  994.  
  995. chdisp proc near
  996.        push   ax
  997.        push   dx
  998.        mov    dl, al
  999.        @doscall 2
  1000.        pop    dx
  1001.        pop    ax
  1002.        ret
  1003. chdisp endp
  1004.  
  1005.  
  1006. ; ---- STRDISP ----------------------------
  1007. ; Display the string at DS:DX on the CRT
  1008. ; Entry:
  1009. ;   DS:DX ==> string
  1010. ; Exit:
  1011. ;   All regs restored
  1012. ; -----------------------------------------
  1013.  
  1014. strdisp proc near
  1015.         push      ds
  1016.         push      cs
  1017.         pop       ds
  1018.         push      ax
  1019.         @doscall 9
  1020.         pop       ax
  1021.         pop       ds
  1022.         ret
  1023. strdisp endp
  1024.  
  1025.  
  1026. ; ----- INCPTR ------------------------------
  1027. ; Increments the buffer pointer in reg BX.
  1028. ; If the pointer goes beyond the end of the
  1029. ; buffer, wrap around to start.
  1030. ;
  1031. ; Entry:
  1032. ;   BX = buffer pointer
  1033. ; Exit
  1034. ;   BX = advanced buffer pointer
  1035. ;   Other regs restored
  1036. ; --------------------------------------------
  1037.  
  1038. incptr proc near
  1039.        push    ax
  1040.        inc     bx                            ; Bump pointer
  1041.        lea     ax, bufend[bp]
  1042.        cmp     bx, ax                        ; Past end?
  1043.        jne     IP100                         ; Jump if not
  1044.        lea     bx, buffer[bp]                ; Else point to start
  1045. IP100: pop     ax
  1046.        ret
  1047. incptr endp
  1048.  
  1049. telecomm endp
  1050. code     ends
  1051.          end   telecomm
  1052.